<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://mourning-soul.gitee.io/hexo/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/hexo/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/hexo/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/hexo/css/style.css">

  
    
<link rel="stylesheet" href="/hexo/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.3.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/hexo/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/hexo/">Home</a>
        
          <a class="main-nav-link" href="/hexo/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/hexo/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://mourning-soul.gitee.io/hexo"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  
    <article id="post-视频直播" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/02/05/%E8%A7%86%E9%A2%91%E7%9B%B4%E6%92%AD/" class="article-date">
  <time class="dt-published" datetime="2021-02-04T16:00:00.000Z" itemprop="datePublished">2021-02-05</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/02/05/%E8%A7%86%E9%A2%91%E7%9B%B4%E6%92%AD/">视频直播</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="直播：流式传输协议，传输非常短的一小截视频"><a href="#直播：流式传输协议，传输非常短的一小截视频" class="headerlink" title="直播：流式传输协议，传输非常短的一小截视频"></a>直播：流式传输协议，传输非常短的一小截视频</h2><hr>
<br>

<h2 id="直播需要："><a href="#直播需要：" class="headerlink" title="直播需要："></a>直播需要：</h2><ul>
<li>直播服务器：云主机</li>
<li>OBS:推流工具：将现场的视频信号传到网络的过程，对网络要求比较高</li>
<li>VLC：拉流工具: 服务器已有直播内容，根据协议类型（如RTMP、RTP、RTSP、HTTP等），与服务器建立连接并接收数据，进行拉取的过程</li>
<li>使用到了rtmp协议还有video标签</li>
</ul>
<hr>
<br>

<h2 id="RTMP直播协议"><a href="#RTMP直播协议" class="headerlink" title="RTMP直播协议"></a>RTMP直播协议</h2><h3 id="RTMP-是专为流媒体开发的协议，对底层的优化比其它协议更加优秀"><a href="#RTMP-是专为流媒体开发的协议，对底层的优化比其它协议更加优秀" class="headerlink" title="RTMP 是专为流媒体开发的协议，对底层的优化比其它协议更加优秀"></a>RTMP 是专为流媒体开发的协议，对底层的<strong>优化</strong>比其它协议更加优秀</h3><hr>
<h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><ul>
<li>  它对 Adobe Flash 支持好</li>
<li>  基本上所有的编码器（摄像头之类）都支持 RTMP 输出</li>
<li>  另外RTMP适合长时间播放，即 10 天多连续播放没有出现问题，稳定</li>
<li>  最后 RTMP 的延迟<strong>相对较低</strong>，一般延时在 1-3s 之间，一般的视频会议，互动式直播，完全是够用的</li>
</ul>
<hr>
<p>缺点</p>
<ul>
<li>  它是基于 TCP 传输，非公共端口，可能会被防火墙阻拦，1935</li>
<li>  RTMP 为 Adobe 私有协议，很多设备无法播放，兼容性不高</li>
<li>  Html基础支持不好，无法直接使用HTML标签完成拉流</li>
</ul>
<hr>
<br>

<h2 id="HTTP-FLV直播协议"><a href="#HTTP-FLV直播协议" class="headerlink" title="HTTP-FLV直播协议"></a>HTTP-FLV直播协议</h2><ul>
<li>  Youtube，B站</li>
</ul>
<h3 id="流媒体数据封装成-FLV-格式"><a href="#流媒体数据封装成-FLV-格式" class="headerlink" title="流媒体数据封装成 FLV 格式"></a>流媒体数据封装成 FLV 格式</h3><h3 id="FLV-简单轻量、加载速度极快、播放快、"><a href="#FLV-简单轻量、加载速度极快、播放快、" class="headerlink" title="FLV: 简单轻量、加载速度极快、播放快、"></a>FLV: 简单轻量、加载速度极快、播放快、</h3><ol>
<li> 推流，服务器把视频封装为.flv 一段段</li>
<li> 浏览器拉流，下载视频</li>
<li> Content-Type: rtmp/flv</li>
</ol>
<hr>
<p>优点</p>
<ul>
<li>可以直接通过http协议进行传输，http属于公共协议，公共端口：80<ul>
<li>  html播放视频就很简单， video</li>
</ul>
</li>
<li>  支持加密，使用https</li>
<li>  兼容移动端设备，比如：安卓、ios</li>
</ul>
<hr>
<p>缺点</p>
<ul>
<li>  会缓存直播数据，保存直播传输过来的一段段flv文件，隐私保密不好</li>
<li>  不能在大并发情况下使用</li>
</ul>
<hr>
<br>

<h2 id="HLS直播协议"><a href="#HLS直播协议" class="headerlink" title="HLS直播协议"></a>HLS直播协议</h2><ul>
<li>  苹果公司的</li>
</ul>
<hr>
<ul>
<li>  对于苹果系列产品支持优秀</li>
<li>  兼容性ok，通过 HTTP 传输</li>
</ul>
<hr>
<ul>
<li>  延迟极高，60s都是可以接收的</li>
<li>  ts 切片较小，会造成海量小文件，保存麻烦，缓存麻烦</li>
</ul>
<hr>
<br>

<h2 id="搭建HTTP-FLV直播"><a href="#搭建HTTP-FLV直播" class="headerlink" title="搭建HTTP-FLV直播"></a>搭建HTTP-FLV直播</h2><ul>
<li>创建软件的储存位置</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mkdir &#x2F;usr&#x2F;local&#x2F;nginx-flv</span><br><span class="line">&#x2F;&#x2F; 创建了一个安装目录</span><br><span class="line">mkdir &#x2F;home&#x2F;flv-tools</span><br><span class="line">&#x2F;&#x2F; 存储所需软件</span><br></pre></td></tr></table></figure>
<ul>
<li>下载nginx</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http:&#x2F;&#x2F;nginx.org&#x2F;download&#x2F;nginx-1.10.3.tar.gz</span><br></pre></td></tr></table></figure>
<ul>
<li>下载直播模块</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https:&#x2F;&#x2F;github.com&#x2F;arut&#x2F;nginx-rtmp-module</span><br></pre></td></tr></table></figure>
<ul>
<li>解压下载好的rtmp直播模块</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unzip nginx-rtmp-module-master.zip </span><br></pre></td></tr></table></figure>
<ul>
<li>创建nginx的安装目录</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir &#x2F;usr&#x2F;local&#x2F;nginx-rtmp</span><br></pre></td></tr></table></figure>
<ul>
<li>配置前，要先记得安装依赖</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel </span><br></pre></td></tr></table></figure>
<ul>
<li>配置nginx安装过程，搭配直播模块使用(nginx-rtmp-module)</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd nginx-1.10.3</span><br><span class="line">.&#x2F;configure --add-module&#x3D;&#x2F;home&#x2F;rtmp-tools&#x2F;nginx-rtmp-module-master&#x2F; --with-http_ssl_module --prefix&#x3D;&#x2F;usr&#x2F;local&#x2F;nginx-rtmp</span><br></pre></td></tr></table></figure>
<ul>
<li>编译</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make</span><br></pre></td></tr></table></figure>
<ul>
<li>安装</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make install</span><br></pre></td></tr></table></figure>
<ul>
<li>修改配置文件</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;usr&#x2F;local&#x2F;nginx-rtmp&#x2F;conf</span><br><span class="line">vim nginx.conf</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">rtmp &#123;</span><br><span class="line">    server &#123;</span><br><span class="line">        listen 1935;</span><br><span class="line">        application live &#123;</span><br><span class="line">            live on;</span><br><span class="line">            record off;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>配置文件http拉流部分</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">http &#123;</span><br><span class="line">	include       mime.types;</span><br><span class="line">	default_type  application&#x2F;octet-stream;</span><br><span class="line">	sendfile        on;</span><br><span class="line">	keepalive_timeout  65;</span><br><span class="line">	server &#123;</span><br><span class="line">		listen       8080; # 拉流通过8080去拉流</span><br><span class="line">		# http:&#x2F;&#x2F;123.123.123.123:8080&#x2F;live&#x2F;?port&#x3D;1935&amp;stream&#x3D;test</span><br><span class="line">		server_name  localhost;</span><br><span class="line">		location &#x2F;live &#123;</span><br><span class="line">			flv_live on;</span><br><span class="line">			chunked_transfer_encoding  on;</span><br><span class="line">			add_header &#39;Access-Control-Allow-Origin&#39; &#39;*&#39;;</span><br><span class="line">			add_header &#39;Access-Control-Allow-Credentials&#39; &#39;true&#39;;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>关闭旧有服务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;usr&#x2F;local&#x2F;nginx-rtmp&#x2F;sbin&#x2F;nginx -s stop</span><br><span class="line">&#x2F;usr&#x2F;local&#x2F;nginx-rtmp&#x2F;sbin&#x2F;nginx -s reload</span><br></pre></td></tr></table></figure>
<ul>
<li>开启新服务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;usr&#x2F;local&#x2F;nginx-flv&#x2F;sbin&#x2F;nginx -c &#x2F;usr&#x2F;local&#x2F;nginx-flv&#x2F;conf&#x2F;nginx.conf</span><br></pre></td></tr></table></figure>
<br>

<hr>
<h2 id="记得打开阿里云的防火墙"><a href="#记得打开阿里云的防火墙" class="headerlink" title="记得打开阿里云的防火墙"></a>记得打开阿里云的防火墙</h2><hr>
<br>

<h2 id="打开OBS进行推流配置"><a href="#打开OBS进行推流配置" class="headerlink" title="打开OBS进行推流配置"></a>打开OBS进行推流配置</h2><p>推流地址为:rtmp://云主机IP及端口/live/自定义密钥</p>
<hr>
<h2 id="打开VLC进行拉流"><a href="#打开VLC进行拉流" class="headerlink" title="打开VLC进行拉流"></a>打开VLC进行拉流</h2><p>拉流地址：http://云主机IP及端口/live?port=端口&amp;app=live&amp;stream=密钥</p>
<hr>
<br>

<h2 id="Vue实现拉流"><a href="#Vue实现拉流" class="headerlink" title="Vue实现拉流"></a>Vue实现拉流</h2><h3 id="安装flv-js开源工具，进行拉流"><a href="#安装flv-js开源工具，进行拉流" class="headerlink" title="安装flv.js开源工具，进行拉流"></a>安装flv.js开源工具，进行拉流</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cnpm install flv.js --save</span><br></pre></td></tr></table></figure>
<h3 id="导包"><a href="#导包" class="headerlink" title="导包"></a>导包</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import flv from &#39;flv.js&#39;</span><br></pre></td></tr></table></figure>
<h3 id="构建页面标签，播放标签"><a href="#构建页面标签，播放标签" class="headerlink" title="构建页面标签，播放标签"></a>构建页面标签，播放标签</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;video id&#x3D;&quot;videoElement&quot; controls muted&gt;</span><br><span class="line">  	Your browser is too old which doesn&#39;t support HTML5 video.</span><br><span class="line">&lt;&#x2F;video&gt;</span><br></pre></td></tr></table></figure>
<h3 id="进行初始化"><a href="#进行初始化" class="headerlink" title="进行初始化"></a>进行初始化</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">mounted() &#123;</span><br><span class="line">    var videoElement &#x3D; document.getElementById(&#39;videoElement&#39;);</span><br><span class="line">    var flvPlayer &#x3D; flv.createPlayer(&#123;</span><br><span class="line">      type: &#39;flv&#39;,</span><br><span class="line">      enableWorker: true,     &#x2F;&#x2F;浏览器端开启flv.js的worker,多进程运行flv.js</span><br><span class="line">      isLive: true,           &#x2F;&#x2F;直播模式</span><br><span class="line">      hasAudio: false,        &#x2F;&#x2F;关闭音频</span><br><span class="line">      hasVideo: true,</span><br><span class="line">      &#x2F;&#x2F; cors: true,</span><br><span class="line">      stashInitialSize: 128,</span><br><span class="line">      enableStashBuffer: false, &#x2F;&#x2F;播放flv时，设置是否启用播放缓存，只在直播起作用。</span><br><span class="line">      url: &#39;http:&#x2F;&#x2F;云主机IP及端口&#x2F;live?port&#x3D;端口&amp;app&#x3D;live&amp;stream&#x3D;密钥&#39;</span><br><span class="line">    &#125;)</span><br><span class="line">    flvPlayer.attachMediaElement(videoElement);</span><br><span class="line">    flvPlayer.load();</span><br><span class="line">    flvPlayer.play();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/02/05/%E8%A7%86%E9%A2%91%E7%9B%B4%E6%92%AD/" data-id="ckkt9opgd000oi4twapbgd430" data-title="视频直播" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-无限极分类自关联递归" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/02/04/%E6%97%A0%E9%99%90%E6%9E%81%E5%88%86%E7%B1%BB%E8%87%AA%E5%85%B3%E8%81%94%E9%80%92%E5%BD%92/" class="article-date">
  <time class="dt-published" datetime="2021-02-03T16:00:00.000Z" itemprop="datePublished">2021-02-04</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/02/04/%E6%97%A0%E9%99%90%E6%9E%81%E5%88%86%E7%B1%BB%E8%87%AA%E5%85%B3%E8%81%94%E9%80%92%E5%BD%92/">无限极分类自关联递归</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="无限极分类自关联"><a href="#无限极分类自关联" class="headerlink" title="无限极分类自关联"></a>无限极分类自关联</h2><h3 id="简介：无限极分类就像一个树状图，从顶级父类开始向下延伸，延伸的点可以看做一个子类，但同时也可以作为父类向下继续延伸"><a href="#简介：无限极分类就像一个树状图，从顶级父类开始向下延伸，延伸的点可以看做一个子类，但同时也可以作为父类向下继续延伸" class="headerlink" title="简介：无限极分类就像一个树状图，从顶级父类开始向下延伸，延伸的点可以看做一个子类，但同时也可以作为父类向下继续延伸"></a>简介：无限极分类就像一个树状图，从顶级父类开始向下延伸，延伸的点可以看做一个子类，但同时也可以作为父类向下继续延伸</h3><hr>
<br>

<ul>
<li>创建一个模型类</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">class Cate(models.Model):</span><br><span class="line">    # 分类名称</span><br><span class="line">    name &#x3D; models.CharField(max_length&#x3D;500)</span><br><span class="line">    # 父级id</span><br><span class="line">    pid &#x3D; models.IntegerField()</span><br><span class="line"></span><br><span class="line">    # 表名</span><br><span class="line">    class Meta:</span><br><span class="line">        db_table &#x3D; &#39;cate&#39;</span><br></pre></td></tr></table></figure>
<hr>
<br>

<ul>
<li>序列化器类</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">from rest_framework import serializers</span><br><span class="line">from .models import Cate</span><br><span class="line">class CateSer(serializers.ModelSerializer):</span><br><span class="line">    class Meta:</span><br><span class="line">        model &#x3D; Cate</span><br><span class="line">        fields &#x3D; &quot;__all__&quot;</span><br></pre></td></tr></table></figure>
<ul>
<li>django序列化出来的类不具备层级结构，提前写好用来递归的方法</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">def xTree(datas):</span><br><span class="line">    lists &#x3D; []</span><br><span class="line">    tree &#x3D; &#123;&#125;</span><br><span class="line">    parent_id &#x3D; &#39;&#39;</span><br><span class="line">    for i in datas:</span><br><span class="line">        item &#x3D; i</span><br><span class="line">        print(item)</span><br><span class="line">        tree[item[&#39;id&#39;]] &#x3D; item</span><br><span class="line">    root &#x3D; None</span><br><span class="line">    for i in datas:</span><br><span class="line">        obj &#x3D; i</span><br><span class="line">        if not obj[&#39;pid&#39;]:</span><br><span class="line">            root &#x3D; tree[obj[&#39;id&#39;]]</span><br><span class="line">            lists.append(root)</span><br><span class="line">        else:</span><br><span class="line">            parent_id &#x3D; obj[&#39;pid&#39;]</span><br><span class="line">            if &#39;childlist&#39; not in tree[parent_id]:</span><br><span class="line">                tree[parent_id][&#39;childlist&#39;] &#x3D; []</span><br><span class="line">            tree[parent_id][&#39;childlist&#39;].append(tree[obj[&#39;id&#39;]])</span><br><span class="line">    return lists</span><br></pre></td></tr></table></figure>
<ul>
<li>写一个视图接口，用来从数据库中读取数据</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">class MyTree(APIView):</span><br><span class="line">    def get(self, request):</span><br><span class="line">        # 获取订单列表</span><br><span class="line">        catelist &#x3D; Cate.objects.all()</span><br><span class="line">        # 序列化</span><br><span class="line">        catelist_ser &#x3D; CateSer(catelist, many&#x3D;True)</span><br><span class="line"></span><br><span class="line">        mylist &#x3D; xTree(catelist_ser.data)</span><br><span class="line">        print(mylist)</span><br><span class="line">        return Response(mylist)</span><br></pre></td></tr></table></figure>
<ul>
<li>postman测试结果</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;id&quot;:1,</span><br><span class="line">        &quot;name&quot;:&quot;品牌&quot;,</span><br><span class="line">        &quot;pid&quot;:0,</span><br><span class="line">        &quot;childlist&quot;:[</span><br><span class="line">            &#123;</span><br><span class="line">                &quot;id&quot;:2</span><br><span class="line">                &quot;name&quot;:&quot;美邦&quot;</span><br><span class="line">                &quot;pid&quot;:1</span><br><span class="line">            &#125;</span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/02/04/%E6%97%A0%E9%99%90%E6%9E%81%E5%88%86%E7%B1%BB%E8%87%AA%E5%85%B3%E8%81%94%E9%80%92%E5%BD%92/" data-id="ckkt9opgc000mi4twh9tgf6sy" data-title="无限极分类自关联递归" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-webshell" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/02/03/webshell/" class="article-date">
  <time class="dt-published" datetime="2021-02-02T16:00:00.000Z" itemprop="datePublished">2021-02-03</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/02/03/webshell/">webshell</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="什么是webshell"><a href="#什么是webshell" class="headerlink" title="什么是webshell"></a>什么是webshell</h2><h3 id="webshell是web入侵的脚本攻击工具。"><a href="#webshell是web入侵的脚本攻击工具。" class="headerlink" title="webshell是web入侵的脚本攻击工具。"></a>webshell是web入侵的脚本攻击工具。</h3><h3 id="简单的说来，webshell就是一个asp或php木马后门，黑客在入侵了一个网站后，常常在将这些asp或php木马后门文件放置在网站服务器的web目录中，与正常的网页文件混在一起。然后黑客就可以用web的方式，通过asp或php木马后门控制网站服务器，包括上传下载文件、查看数据库、执行任意程序命令等。"><a href="#简单的说来，webshell就是一个asp或php木马后门，黑客在入侵了一个网站后，常常在将这些asp或php木马后门文件放置在网站服务器的web目录中，与正常的网页文件混在一起。然后黑客就可以用web的方式，通过asp或php木马后门控制网站服务器，包括上传下载文件、查看数据库、执行任意程序命令等。" class="headerlink" title="简单的说来，webshell就是一个asp或php木马后门，黑客在入侵了一个网站后，常常在将这些asp或php木马后门文件放置在网站服务器的web目录中，与正常的网页文件混在一起。然后黑客就可以用web的方式，通过asp或php木马后门控制网站服务器，包括上传下载文件、查看数据库、执行任意程序命令等。"></a>简单的说来，webshell就是一个asp或php木马后门，黑客在入侵了一个网站后，常常在将这些asp或php木马后门文件放置在网站服务器的web目录中，与正常的网页文件混在一起。然后黑客就可以用web的方式，通过asp或php木马后门控制网站服务器，包括上传下载文件、查看数据库、执行任意程序命令等。</h3><hr>
<br>

<h2 id="什么是“木马”？"><a href="#什么是“木马”？" class="headerlink" title="什么是“木马”？"></a>什么是“木马”？</h2><h3 id="“木马”全称是“特洛伊木马-Trojan-Horse-”，原指古希腊士兵藏在木马内进入敌方城市从而占领敌方城市的故事。"><a href="#“木马”全称是“特洛伊木马-Trojan-Horse-”，原指古希腊士兵藏在木马内进入敌方城市从而占领敌方城市的故事。" class="headerlink" title="“木马”全称是“特洛伊木马(Trojan  Horse)”，原指古希腊士兵藏在木马内进入敌方城市从而占领敌方城市的故事。"></a>“木马”全称是“特洛伊木马(Trojan <B r> Horse)”，原指古希腊士兵藏在木马内进入敌方城市从而占领敌方城市的故事。</B></h3><h3 id="在Internet上，“特洛伊木马”指一些程序设计人员在其可从网络上下载-Download-的应用程序或游戏中，包含了可以控制用户的计算机系统的程序，可能造成用户的系统被破坏甚至瘫痪。"><a href="#在Internet上，“特洛伊木马”指一些程序设计人员在其可从网络上下载-Download-的应用程序或游戏中，包含了可以控制用户的计算机系统的程序，可能造成用户的系统被破坏甚至瘫痪。" class="headerlink" title="在Internet上，“特洛伊木马”指一些程序设计人员在其可从网络上下载 (Download)的应用程序或游戏中，包含了可以控制用户的计算机系统的程序，可能造成用户的系统被破坏甚至瘫痪。"></a>在Internet上，“特洛伊木马”指一些程序设计人员在其可从网络上下载 (Download)的应用程序或游戏中，包含了可以控制用户的计算机系统的程序，可能造成用户的系统被破坏甚至瘫痪。</h3><hr>
<br>

<h2 id="什么是后门？"><a href="#什么是后门？" class="headerlink" title="什么是后门？"></a>什么是后门？</h2><h3 id="大家都知道，一台计算机上有65535个端口，那么如果把计算机看作是一间屋子，那么这65535个端口就可以它看做是计算机为了与外界连接所开的65535-扇门。每个门的背后都是一个服务。有的门是主人特地打开迎接客人的（提供服务），有的门是主人为了出去访问客人而开设的（访问远程服务）——理论上，剩下的其他门都该是关闭着的，但偏偏由于各种原因，很多门都是开启的。于是就有好事者进入，主人的隐私被刺探，生活被打扰，甚至屋里的东西也被搞得一片狼迹。这扇悄然被开启的门——就是“后门”。"><a href="#大家都知道，一台计算机上有65535个端口，那么如果把计算机看作是一间屋子，那么这65535个端口就可以它看做是计算机为了与外界连接所开的65535-扇门。每个门的背后都是一个服务。有的门是主人特地打开迎接客人的（提供服务），有的门是主人为了出去访问客人而开设的（访问远程服务）——理论上，剩下的其他门都该是关闭着的，但偏偏由于各种原因，很多门都是开启的。于是就有好事者进入，主人的隐私被刺探，生活被打扰，甚至屋里的东西也被搞得一片狼迹。这扇悄然被开启的门——就是“后门”。" class="headerlink" title="大家都知道，一台计算机上有65535个端口，那么如果把计算机看作是一间屋子，那么这65535个端口就可以它看做是计算机为了与外界连接所开的65535 扇门。每个门的背后都是一个服务。有的门是主人特地打开迎接客人的（提供服务），有的门是主人为了出去访问客人而开设的（访问远程服务）——理论上，剩下的其他门都该是关闭着的，但偏偏由于各种原因，很多门都是开启的。于是就有好事者进入，主人的隐私被刺探，生活被打扰，甚至屋里的东西也被搞得一片狼迹。这扇悄然被开启的门——就是“后门”。"></a>大家都知道，一台计算机上有65535个端口，那么如果把计算机看作是一间屋子，那么这65535个端口就可以它看做是计算机为了与外界连接所开的65535 扇门。每个门的背后都是一个服务。有的门是主人特地打开迎接客人的（提供服务），有的门是主人为了出去访问客人而开设的（访问远程服务）——理论上，剩下的其他门都该是关闭着的，但偏偏由于各种原因，很多门都是开启的。于是就有好事者进入，主人的隐私被刺探，生活被打扰，甚至屋里的东西也被搞得一片狼迹。这扇悄然被开启的门——就是“后门”。</h3><hr>
<br>

<h2 id="webshell的优点"><a href="#webshell的优点" class="headerlink" title="webshell的优点"></a>webshell的优点</h2><h3 id="webshell-最大的优点就是可以穿越防火墙，由于与被控制的服务器或远程主机交换的数据都是通过80端口传递的，因此不会被防火墙拦截。并且使用webshell一般不会在系统日志中留下记录，只会在网站的web日志中留下一些数据提交记录，没有经验的管理员是很难看出入侵痕迹的。"><a href="#webshell-最大的优点就是可以穿越防火墙，由于与被控制的服务器或远程主机交换的数据都是通过80端口传递的，因此不会被防火墙拦截。并且使用webshell一般不会在系统日志中留下记录，只会在网站的web日志中留下一些数据提交记录，没有经验的管理员是很难看出入侵痕迹的。" class="headerlink" title="webshell 最大的优点就是可以穿越防火墙，由于与被控制的服务器或远程主机交换的数据都是通过80端口传递的，因此不会被防火墙拦截。并且使用webshell一般不会在系统日志中留下记录，只会在网站的web日志中留下一些数据提交记录，没有经验的管理员是很难看出入侵痕迹的。"></a>webshell 最大的优点就是可以穿越防火墙，由于与被控制的服务器或远程主机交换的数据都是通过80端口传递的，因此不会被防火墙拦截。并且使用webshell一般不会在系统日志中留下记录，只会在网站的web日志中留下一些数据提交记录，没有经验的管理员是很难看出入侵痕迹的。</h3><hr>
<br>

<h2 id="webshell的原理"><a href="#webshell的原理" class="headerlink" title="webshell的原理"></a>webshell的原理</h2><ol>
<li>可执行脚本 </li>
</ol>
<ul>
<li>HTTP数据包($_GET、$_POST、$_COOKIES、$_SERVER[args]等)</li>
</ul>
<ol start="2">
<li><p>数据传递</p>
</li>
<li><p>执行传递的数据 </p>
</li>
</ol>
<ul>
<li><p>直接执行(eval、system、passthru等) </p>
</li>
<li><p>文件包含执行(include、require等) </p>
</li>
<li><p>动态函数执行($a=”phpinfo”;$a();) </p>
</li>
<li><p>Curly Syntax执行(${‘ls’}) </p>
</li>
<li><p>preg_replace(第一个参数存在’/e’) </p>
</li>
<li><p>ob_start函数 </p>
</li>
<li><p>回调函数(array_map等) </p>
</li>
<li><p>反序列化(unserialize等)</p>
</li>
</ul>
<hr>
<br>

<h2 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h2><h3 id="安装组件"><a href="#安装组件" class="headerlink" title="安装组件"></a>安装组件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install xterm@3.1.0 --save</span><br></pre></td></tr></table></figure>
<h3 id="在main-js文件中导入css样式"><a href="#在main-js文件中导入css样式" class="headerlink" title="在main.js文件中导入css样式"></a>在main.js文件中导入css样式</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import &#39;xterm&#x2F;dist&#x2F;xterm.css&#39; </span><br></pre></td></tr></table></figure>
<h3 id="在你对应的页面上放上这个div标签，这就是那个黑窗口"><a href="#在你对应的页面上放上这个div标签，这就是那个黑窗口" class="headerlink" title="在你对应的页面上放上这个div标签，这就是那个黑窗口"></a>在你对应的页面上放上这个div标签，这就是那个黑窗口</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;div id&#x3D;&quot;terminal&quot;&gt;</span><br><span class="line">&lt;&#x2F;div&gt;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">import &#123; Terminal &#125; from &#39;xterm&#39;</span><br><span class="line">import * as attach from &#39;xterm&#x2F;lib&#x2F;addons&#x2F;attach&#x2F;attach&#39; &#x2F;&#x2F; 安装插件适，可以使用attach去添加</span><br><span class="line">import * as fit from &#39;xterm&#x2F;lib&#x2F;addons&#x2F;fit&#x2F;fit&#39; &#x2F;&#x2F; fit进行自适应大小的</span><br><span class="line"></span><br><span class="line">Terminal.applyAddon(attach) &#x2F;&#x2F; 添加插件</span><br><span class="line">Terminal.applyAddon(fit) &#x2F;&#x2F; 添加插件</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 获取到了div标签</span><br><span class="line">let terminalContainer &#x3D; document.getElementById(&#39;terminal&#39;)</span><br><span class="line">&#x2F;&#x2F; 初始化黑窗口对象</span><br><span class="line">this.term &#x3D; new Terminal(this.terminal)</span><br><span class="line">&#x2F;&#x2F; 打开这个对象</span><br><span class="line">this.term.open(terminalContainer)</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/02/03/webshell/" data-id="ckkt9opg6000ii4tw8anrb0uh" data-title="webshell" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-redis键空间事件" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/02/02/redis%E9%94%AE%E7%A9%BA%E9%97%B4%E4%BA%8B%E4%BB%B6/" class="article-date">
  <time class="dt-published" datetime="2021-02-01T16:00:00.000Z" itemprop="datePublished">2021-02-02</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/02/02/redis%E9%94%AE%E7%A9%BA%E9%97%B4%E4%BA%8B%E4%BB%B6/">redis键空间事件</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="redis键空间事件简介"><a href="#redis键空间事件简介" class="headerlink" title="redis键空间事件简介"></a>redis键空间事件简介</h2><h3 id="Redis从2-8-0版本后，推出-Keyspace-Notifications-特性。"><a href="#Redis从2-8-0版本后，推出-Keyspace-Notifications-特性。" class="headerlink" title="Redis从2.8.0版本后，推出 Keyspace Notifications 特性。"></a>Redis从2.8.0版本后，推出 Keyspace Notifications 特性。</h3><h3 id="Keyspace-Notifications-此特性允许客户端可以以-订阅-发布（Sub-Pub）模式，接收那些对数据库中的键和值有影响的操作事件。这些操作事件具体来说，就是-del-expire-set-rpop等"><a href="#Keyspace-Notifications-此特性允许客户端可以以-订阅-发布（Sub-Pub）模式，接收那些对数据库中的键和值有影响的操作事件。这些操作事件具体来说，就是-del-expire-set-rpop等" class="headerlink" title="Keyspace Notifications 此特性允许客户端可以以 订阅/发布（Sub/Pub）模式，接收那些对数据库中的键和值有影响的操作事件。这些操作事件具体来说，就是 del , expire , set , rpop等"></a>Keyspace Notifications 此特性允许客户端可以以 订阅/发布（Sub/Pub）模式，接收那些对数据库中的键和值有影响的操作事件。这些操作事件具体来说，就是 del , expire , set , rpop等</h3><hr>
<br>

<h2 id="接收的事件的类型"><a href="#接收的事件的类型" class="headerlink" title="接收的事件的类型"></a>接收的事件的类型</h2><h3 id="接收到的事件的类型只有两种：-keyspace-和-keyevent。"><a href="#接收到的事件的类型只有两种：-keyspace-和-keyevent。" class="headerlink" title="接收到的事件的类型只有两种： keyspace 和 keyevent。"></a>接收到的事件的类型只有两种： keyspace 和 keyevent。</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">PUBLISH __keyspace@0__:mykey del</span><br><span class="line">PUBLISH __keyevent@0__:del mykey</span><br></pre></td></tr></table></figure>
<h3 id="第一条信息的通道名称有-keyspace-前缀，是-keyspace-类型，内容为具体操作-del-。第二条信息的通道名称有-keyevent-前缀，是-keyevent-类型，内容为影响的键名-mykey。"><a href="#第一条信息的通道名称有-keyspace-前缀，是-keyspace-类型，内容为具体操作-del-。第二条信息的通道名称有-keyevent-前缀，是-keyevent-类型，内容为影响的键名-mykey。" class="headerlink" title="第一条信息的通道名称有 keyspace 前缀，是 keyspace 类型，内容为具体操作 del 。第二条信息的通道名称有 keyevent 前缀，是 keyevent 类型，内容为影响的键名 mykey。"></a>第一条信息的通道名称有 keyspace 前缀，是 keyspace 类型，内容为具体操作 del 。第二条信息的通道名称有 keyevent 前缀，是 keyevent 类型，内容为影响的键名 mykey。</h3><hr>
<br>

<h2 id="Keyspace-Notifications-空间通知特性的开启"><a href="#Keyspace-Notifications-空间通知特性的开启" class="headerlink" title="Keyspace Notifications 空间通知特性的开启"></a>Keyspace Notifications 空间通知特性的开启</h2><br>

<h3 id="这里需要修改redis的配置文件redis-conf，使此特性开启。默认情况下，redis是不开启此特性的。"><a href="#这里需要修改redis的配置文件redis-conf，使此特性开启。默认情况下，redis是不开启此特性的。" class="headerlink" title="这里需要修改redis的配置文件redis.conf，使此特性开启。默认情况下，redis是不开启此特性的。"></a>这里需要修改redis的配置文件redis.conf，使此特性开启。默认情况下，redis是不开启此特性的。</h3><h3 id="首先找到-redis-conf-（我的配置文件是在-usr-local-redis-etc-路径下），vim-打开，搜索一下-notify-keyspace-events。"><a href="#首先找到-redis-conf-（我的配置文件是在-usr-local-redis-etc-路径下），vim-打开，搜索一下-notify-keyspace-events。" class="headerlink" title="首先找到 redis.conf （我的配置文件是在 /usr/local/redis/etc/ 路径下），vim 打开，搜索一下 notify-keyspace-events。"></a>首先找到 redis.conf （我的配置文件是在 /usr/local/redis/etc/ 路径下），vim 打开，搜索一下 notify-keyspace-events。</h3><h3 id="可以下看到如下"><a href="#可以下看到如下" class="headerlink" title="可以下看到如下"></a>可以下看到如下</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">notify-keyspace-events &quot;&quot;</span><br></pre></td></tr></table></figure>
<hr>
<br>

<h2 id="接收键空间的通知"><a href="#接收键空间的通知" class="headerlink" title="接收键空间的通知"></a>接收键空间的通知</h2><h3 id="开启一个终端，redis-cli-进入-redis-。开始订阅所有操作，等待接收消息。"><a href="#开启一个终端，redis-cli-进入-redis-。开始订阅所有操作，等待接收消息。" class="headerlink" title="开启一个终端，redis-cli 进入 redis 。开始订阅所有操作，等待接收消息。"></a>开启一个终端，redis-cli 进入 redis 。开始订阅所有操作，等待接收消息。</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[root@chokingwin etc]# redis-cli</span><br><span class="line">127.0.0.1:6379&gt; psubscribe __key*@0__:*</span><br><span class="line">Reading messages... (press Ctrl-C to quit)</span><br><span class="line">1) &quot;psubscribe&quot;</span><br><span class="line">2) &quot;__key*@0__:*&quot;</span><br><span class="line">3) (integer) 1</span><br></pre></td></tr></table></figure>
<h3 id="再开启一个终端，redis-cli-进入-redis-，设置一个string类型的Key，其值为-chokingwin。"><a href="#再开启一个终端，redis-cli-进入-redis-，设置一个string类型的Key，其值为-chokingwin。" class="headerlink" title="再开启一个终端，redis-cli 进入 redis ，设置一个string类型的Key，其值为 chokingwin。"></a>再开启一个终端，redis-cli 进入 redis ，设置一个string类型的Key，其值为 chokingwin。</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[root@chokingwin etc]# redis-cli</span><br><span class="line">127.0.0.1:6379&gt; set name chokingwin</span><br><span class="line">OK</span><br></pre></td></tr></table></figure>
<h3 id="随即就会看到，另外一边执行了阻塞订阅操作后的终端，有如下信息输出"><a href="#随即就会看到，另外一边执行了阻塞订阅操作后的终端，有如下信息输出" class="headerlink" title="随即就会看到，另外一边执行了阻塞订阅操作后的终端，有如下信息输出"></a>随即就会看到，另外一边执行了阻塞订阅操作后的终端，有如下信息输出</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&quot;pmessage&quot;</span><br><span class="line">&quot;__key*@0__:*&quot;</span><br><span class="line">&quot;__keyspace@0__:name&quot;</span><br><span class="line">&quot;set&quot;</span><br><span class="line">&quot;pmessage&quot;</span><br><span class="line">&quot;__key*@0__:*&quot;</span><br><span class="line">&quot;__keyevent@0__:set&quot;</span><br><span class="line">&quot;name&quot;</span><br></pre></td></tr></table></figure>
<h3 id="说明键空间消息的接收，是成功的"><a href="#说明键空间消息的接收，是成功的" class="headerlink" title="说明键空间消息的接收，是成功的"></a>说明键空间消息的接收，是成功的</h3>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/02/02/redis%E9%94%AE%E7%A9%BA%E9%97%B4%E4%BA%8B%E4%BB%B6/" data-id="ckkt9opfu0005i4twg4g79vos" data-title="redis键空间事件" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-redis发布者订阅者" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/02/01/redis%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/" class="article-date">
  <time class="dt-published" datetime="2021-01-31T16:00:00.000Z" itemprop="datePublished">2021-02-01</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/02/01/redis%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/">redis发布者订阅者</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="发布者订阅者"><a href="#发布者订阅者" class="headerlink" title="发布者订阅者"></a>发布者订阅者</h2><h3 id="发布与订阅（publish-subscribe）模式，简称为pub-sub模式，是一种消息通信模式-发送者-pub-发送信息-订阅者-sub-订阅消息。redis也实现了这种模式。"><a href="#发布与订阅（publish-subscribe）模式，简称为pub-sub模式，是一种消息通信模式-发送者-pub-发送信息-订阅者-sub-订阅消息。redis也实现了这种模式。" class="headerlink" title="发布与订阅（publish/subscribe）模式，简称为pub/sub模式，是一种消息通信模式 , 发送者(pub)发送信息, 订阅者(sub)订阅消息。redis也实现了这种模式。"></a>发布与订阅（publish/subscribe）模式，简称为pub/sub模式，是一种消息通信模式 , 发送者(pub)发送信息, 订阅者(sub)订阅消息。redis也实现了这种模式。</h3><br>

<h2 id="redis提供的发布订阅命令"><a href="#redis提供的发布订阅命令" class="headerlink" title="redis提供的发布订阅命令"></a>redis提供的发布订阅命令</h2><ul>
<li>subscribe：subscribe channel [channel …] 订阅一个或多个频道</li>
<li>unsubscribe：unsubscribe [channel [channel …]] 退订频道，如果没有指定频道，则退订所有的频道</li>
<li>publish：publish channel message 给指定的频道发消息</li>
<li>psubscribe：psubscribe pattern [pattern …] 订阅给定模式相匹配的所有频道</li>
<li>punsubscribe：punsubscribe [pattern [pattern …]] 退订给定的模式，如果没有指定模式，则退订所有模式</li>
</ul>
<hr>
<br>

<h2 id="发布者"><a href="#发布者" class="headerlink" title="发布者"></a>发布者</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import redis</span><br><span class="line"></span><br><span class="line">conn &#x3D; redis.Redis(host&#x3D;&#39;127.0.0.1&#39;, decode_responses&#x3D;True)</span><br><span class="line"></span><br><span class="line">conn.publish(&#39;xiaoming&#39;, &#39;18&#39;)</span><br></pre></td></tr></table></figure>
<h2 id="订阅者"><a href="#订阅者" class="headerlink" title="订阅者"></a>订阅者</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">import redis</span><br><span class="line"></span><br><span class="line">conn &#x3D; redis.Redis(host&#x3D;&#39;127.0.0.1&#39;, decode_responses&#x3D;True)</span><br><span class="line"></span><br><span class="line"># 生成一个订阅者对象</span><br><span class="line">pubsub &#x3D; conn.pubsub()</span><br><span class="line"></span><br><span class="line"># 订阅一个消息</span><br><span class="line">pubsub.subscribe(&#39;xiaoming&#39;)</span><br><span class="line"></span><br><span class="line"># 创建一个接收</span><br><span class="line">while True:</span><br><span class="line">    print(&#39;working~~~&#39;)</span><br><span class="line">    msg &#x3D; pubsub.parse_response()</span><br><span class="line">    print(msg)</span><br></pre></td></tr></table></figure>
<hr>
<br>

<ul>
<li>运行多个订阅者，每个订阅者会等待接收发布者发送的消息，当发布者发布消息后，订阅者全部接收到</li>
</ul>
<hr>
<br>

<h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h2><h3 id="所有pub-sub很有用，但是redis的实现有这么几个问题："><a href="#所有pub-sub很有用，但是redis的实现有这么几个问题：" class="headerlink" title="所有pub/sub很有用，但是redis的实现有这么几个问题："></a>所有pub/sub很有用，但是redis的实现有这么几个问题：</h3><ol>
<li>如果一个客户端订阅了频道，但自己读取消息的速度却不够快的话，那么不断积压的消息会使redis输出缓冲区的体积变得越来越大，这可能使得redis本身的速度变慢，甚至直接崩溃。 </li>
<li>这和数据传输可靠性有关，如果在订阅方断线，那么他将会丢失所有在短线期间发布者发布的消息，这个让绝不多数人都很失望吧。</li>
</ol>
<hr>
<br>

<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景:"></a>使用场景:</h2><ol>
<li><p>实时消息系统</p>
</li>
<li><p>实时聊天</p>
</li>
<li><p>订阅,关注系统</p>
</li>
</ol>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/02/01/redis%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/" data-id="ckkt9opft0004i4twh38cefxx" data-title="redis发布者订阅者" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-axios封装" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/01/31/axios%E5%B0%81%E8%A3%85/" class="article-date">
  <time class="dt-published" datetime="2021-01-30T16:00:00.000Z" itemprop="datePublished">2021-01-31</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/01/31/axios%E5%B0%81%E8%A3%85/">axios封装</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="首先安装axios"><a href="#首先安装axios" class="headerlink" title="首先安装axios"></a>首先安装axios</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save axios</span><br></pre></td></tr></table></figure>
<hr>
<br>

<h3 id="新建一个http-js和一个api-js文件，http-js文件用来封装我们的axios，api-js用来统一管理我们的接口。"><a href="#新建一个http-js和一个api-js文件，http-js文件用来封装我们的axios，api-js用来统一管理我们的接口。" class="headerlink" title="新建一个http.js和一个api.js文件，http.js文件用来封装我们的axios，api.js用来统一管理我们的接口。"></a>新建一个http.js和一个api.js文件，http.js文件用来封装我们的axios，api.js用来统一管理我们的接口。</h3><hr>
<br>

<h2 id="配置axios"><a href="#配置axios" class="headerlink" title="配置axios"></a>配置axios</h2><h3 id="创建一个http-js文件，这里可以存放axios的配置和请求、响应拦截器"><a href="#创建一个http-js文件，这里可以存放axios的配置和请求、响应拦截器" class="headerlink" title="创建一个http.js文件，这里可以存放axios的配置和请求、响应拦截器"></a>创建一个http.js文件，这里可以存放axios的配置和请求、响应拦截器</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 配置axios基本的属性</span><br><span class="line"></span><br><span class="line">const axios &#x3D; require(&#39;axios&#39;)</span><br><span class="line"></span><br><span class="line">axios.defaults.baseURL &#x3D; &#39;http:&#x2F;&#x2F;127.0.0.1:8000&#39; &#x2F;&#x2F; 请求的接口主域名</span><br><span class="line">axios.defaults.timeout &#x3D; 10000 &#x2F;&#x2F; 请求超时的设置 10s</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 请求拦截器(在请求前会自动去做的操作)，如果登陆了，那么自动带token发送</span><br><span class="line">axios.interceptors.request.use(config &#x3D;&gt; &#123;</span><br><span class="line">  let token &#x3D; localStorage.getItem(&#39;token&#39;);</span><br><span class="line">  if (token) &#123;</span><br><span class="line">    axios.defaults.headers[&#39;Authorization&#39;] &#x3D; token &#x2F;&#x2F; 头部设置</span><br><span class="line">  &#125;</span><br><span class="line">  return config;</span><br><span class="line">&#125;, error &#x3D;&gt; &#123;</span><br><span class="line">  console.log(error)</span><br><span class="line">  return Promise.reject(error);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 响应拦截器(在响应时自动会做的操作)，比如状态码返回为401时，要进入login界面</span><br><span class="line"> axios.interceptors.response.use(response &#x3D;&gt; &#123;</span><br><span class="line">   &#x2F;&#x2F; 200</span><br><span class="line">   return response.data;</span><br><span class="line"> &#125;, error &#x3D;&gt; &#123;</span><br><span class="line">   return error</span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#x2F;**</span><br><span class="line"> * post方法，对应post请求</span><br><span class="line"> * @param &#123;String&#125; url [请求的url地址]</span><br><span class="line"> * @param &#123;Object&#125; params [请求时携带的参数]</span><br><span class="line"> * @param &#123;Object&#125; headers [请求时的头部]</span><br><span class="line"> **&#x2F;</span><br><span class="line">export function get(url, params, headers) &#123;</span><br><span class="line">  return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    axios.get(url, &#123;params, headers&#125;).then(res &#x3D;&gt; &#123;</span><br><span class="line">      resolve(res)</span><br><span class="line">    &#125;).catch(err &#x3D;&gt; &#123;</span><br><span class="line">      reject(err)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export function post(url, params, headers) &#123;</span><br><span class="line">  return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    axios.post(url, params, headers).then((res) &#x3D;&gt; &#123;</span><br><span class="line">      resolve(res)</span><br><span class="line">    &#125;).catch((err) &#x3D;&gt; &#123;</span><br><span class="line">      &#x2F;&#x2F; debugger</span><br><span class="line">      reject(err)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">export function put(url, params, headers) &#123;</span><br><span class="line">  return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    axios.put(url, params, headers).then((res) &#x3D;&gt; &#123;</span><br><span class="line">      resolve(res)</span><br><span class="line">    &#125;).catch((err) &#x3D;&gt; &#123;</span><br><span class="line">      &#x2F;&#x2F; debugger</span><br><span class="line">      reject(err)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export function del(url, params, headers) &#123;</span><br><span class="line">  return new Promise((resolve, reject) &#x3D;&gt; &#123;</span><br><span class="line">    axios.delete(url, &#123;data: params, headers&#125;).then((res) &#x3D;&gt; &#123;</span><br><span class="line">      resolve(res)</span><br><span class="line">    &#125;).catch((err) &#x3D;&gt; &#123;</span><br><span class="line">      &#x2F;&#x2F; debugger</span><br><span class="line">      reject(err)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default axios;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<ul>
<li>注意：<h3 id="我们通过定义一个（post，get，put，delete）函数，函数有两个参数，第一个参数表示我们要请求的url地址，第二个参数是我们要携带的请求参数。函数返回一个promise对象，当axios其请求成功时resolve服务器返回-值，请求失败时reject错误值。最后通过export抛出函数。"><a href="#我们通过定义一个（post，get，put，delete）函数，函数有两个参数，第一个参数表示我们要请求的url地址，第二个参数是我们要携带的请求参数。函数返回一个promise对象，当axios其请求成功时resolve服务器返回-值，请求失败时reject错误值。最后通过export抛出函数。" class="headerlink" title="我们通过定义一个（post，get，put，delete）函数，函数有两个参数，第一个参数表示我们要请求的url地址，第二个参数是我们要携带的请求参数。函数返回一个promise对象，当axios其请求成功时resolve服务器返回 值，请求失败时reject错误值。最后通过export抛出函数。"></a>我们通过定义一个（post，get，put，delete）函数，函数有两个参数，第一个参数表示我们要请求的url地址，第二个参数是我们要携带的请求参数。函数返回一个promise对象，当axios其请求成功时resolve服务器返回 值，请求失败时reject错误值。最后通过export抛出函数。</h3></li>
</ul>
<hr>
<br>

<h2 id="封装请求"><a href="#封装请求" class="headerlink" title="封装请求"></a>封装请求</h2><h3 id="创建一个api-js-文件，存放具体请求"><a href="#创建一个api-js-文件，存放具体请求" class="headerlink" title="创建一个api.js 文件，存放具体请求"></a>创建一个api.js 文件，存放具体请求</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">import &#123;get, post, put, del&#125; from &#39;.&#x2F;index&#39;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;get方法</span><br><span class="line">export const 调用名 &#x3D; parameter &#x3D;&gt; &#123;</span><br><span class="line">  return get(</span><br><span class="line">    &#39;路由地址&#39;,</span><br><span class="line">    parameter,</span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; post方法</span><br><span class="line">export const 调用名 &#x3D; parameter &#x3D;&gt; &#123;</span><br><span class="line">  return post(</span><br><span class="line">    &#39;路由地址&#39;,</span><br><span class="line">    parameter,</span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; put方法</span><br><span class="line">export const 调用名 &#x3D; parameter &#x3D;&gt; &#123;</span><br><span class="line">  return put(</span><br><span class="line">    &#39;路由地址&#39;,</span><br><span class="line">    parameter,</span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; delete方法</span><br><span class="line">export const 调用名 &#x3D; parameter &#x3D;&gt; &#123;</span><br><span class="line">  return del(</span><br><span class="line">    &#39;路由地址&#39;,</span><br><span class="line">    parameter,</span><br><span class="line">  )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="在vue组件中使用"><a href="#在vue组件中使用" class="headerlink" title="在vue组件中使用"></a>在vue组件中使用</h2><h3 id="创建一个-vue文件"><a href="#创建一个-vue文件" class="headerlink" title="创建一个.vue文件"></a>创建一个.vue文件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">import &#123;调用名&#125; from &#39;@&#x2F;api.js&#39;;</span><br><span class="line">export default&#123;</span><br><span class="line">    created()&#123;</span><br><span class="line">        调用名()</span><br><span class="line">        .then(res&#x3D;&gt;&#123;</span><br><span class="line">            console.log(res)</span><br><span class="line">        &#125;)</span><br><span class="line">        .catch(err&#x3D;&gt;&#123;</span><br><span class="line">            console.log(err)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/01/31/axios%E5%B0%81%E8%A3%85/" data-id="ckkt9opfi0000i4tw8gka1f7x" data-title="axios封装" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-celery异步框架(5.0)" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/01/30/celery%E5%BC%82%E6%AD%A5%E6%A1%86%E6%9E%B6(5.0)/" class="article-date">
  <time class="dt-published" datetime="2021-01-29T16:00:00.000Z" itemprop="datePublished">2021-01-30</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/01/30/celery%E5%BC%82%E6%AD%A5%E6%A1%86%E6%9E%B6(5.0)/">celery异步框架5.0</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="celery简介"><a href="#celery简介" class="headerlink" title="celery简介"></a>celery简介</h2><h3 id="Celery是一个简单、灵活且可靠的，处理大量消息的分布式系统，专注于实时处理的异步任务队列，同时也支持任务调度"><a href="#Celery是一个简单、灵活且可靠的，处理大量消息的分布式系统，专注于实时处理的异步任务队列，同时也支持任务调度" class="headerlink" title="Celery是一个简单、灵活且可靠的，处理大量消息的分布式系统，专注于实时处理的异步任务队列，同时也支持任务调度"></a>Celery是一个简单、灵活且可靠的，处理大量消息的分布式系统，专注于实时处理的异步任务队列，同时也支持任务调度</h3><h3 id="celery是一种即插即用的任务队列，它是一个异步任务调度工具，用户使用-Celery-产生任务，借用中间人来传递任务，任务执行单元从中间人那里消费任务。任务执行单元可以单机部署，也可以分布式部署，因此-Celery-是一个高可用的生产者消费者模型的异步任务队列。你可以将你的任务交给-Celery-处理，也可以让-Celery-自动按-crontab-那样去自动调度任务，然后去做其他事情，你可以随时查看任务执行的状态，也可以让-Celery-执行完成后自动把执行结果告诉你。"><a href="#celery是一种即插即用的任务队列，它是一个异步任务调度工具，用户使用-Celery-产生任务，借用中间人来传递任务，任务执行单元从中间人那里消费任务。任务执行单元可以单机部署，也可以分布式部署，因此-Celery-是一个高可用的生产者消费者模型的异步任务队列。你可以将你的任务交给-Celery-处理，也可以让-Celery-自动按-crontab-那样去自动调度任务，然后去做其他事情，你可以随时查看任务执行的状态，也可以让-Celery-执行完成后自动把执行结果告诉你。" class="headerlink" title="celery是一种即插即用的任务队列，它是一个异步任务调度工具，用户使用 Celery 产生任务，借用中间人来传递任务，任务执行单元从中间人那里消费任务。任务执行单元可以单机部署，也可以分布式部署，因此 Celery 是一个高可用的生产者消费者模型的异步任务队列。你可以将你的任务交给 Celery 处理，也可以让 Celery 自动按 crontab 那样去自动调度任务，然后去做其他事情，你可以随时查看任务执行的状态，也可以让 Celery 执行完成后自动把执行结果告诉你。"></a>celery是一种即插即用的<b>任务队列</b>，它是一个异步任务调度工具，用户使用 Celery 产生任务，借用中间人来传递任务，任务执行单元从中间人那里消费任务。任务执行单元可以单机部署，也可以分布式部署，因此 Celery 是一个高可用的生产者消费者模型的异步<b>任务队列</b>。你可以将你的任务交给 Celery 处理，也可以让 Celery 自动按 crontab 那样去自动调度任务，然后去做其他事情，你可以随时查看任务执行的状态，也可以让 Celery 执行完成后自动把执行结果告诉你。</h3><hr>
<br>

<h2 id="celery应用场景"><a href="#celery应用场景" class="headerlink" title="celery应用场景"></a>celery应用场景</h2><h3 id="celery适合异步处理任务，如发送短信、邮件、文件上传、图像处理等比较耗时的操作，可将其异步执行，用户不需要等待太多时间，提高用户体验。"><a href="#celery适合异步处理任务，如发送短信、邮件、文件上传、图像处理等比较耗时的操作，可将其异步执行，用户不需要等待太多时间，提高用户体验。" class="headerlink" title="celery适合异步处理任务，如发送短信、邮件、文件上传、图像处理等比较耗时的操作，可将其异步执行，用户不需要等待太多时间，提高用户体验。"></a>celery适合异步处理任务，如发送短信、邮件、文件上传、图像处理等比较耗时的操作，可将其异步执行，用户不需要等待太多时间，提高用户体验。</h3><hr>
<br>

<h2 id="celery架构"><a href="#celery架构" class="headerlink" title="celery架构"></a>celery架构</h2><h3 id="Celery的架构由三部分组成，消息中间件（message-broker），任务执行单元（worker）和任务执行结果存储（task-result-store）组成。"><a href="#Celery的架构由三部分组成，消息中间件（message-broker），任务执行单元（worker）和任务执行结果存储（task-result-store）组成。" class="headerlink" title="Celery的架构由三部分组成，消息中间件（message broker），任务执行单元（worker）和任务执行结果存储（task result store）组成。"></a>Celery的架构由三部分组成，消息中间件（message broker），任务执行单元（worker）和任务执行结果存储（task result store）组成。</h3><ul>
<li>消息中间件</li>
</ul>
<blockquote>
<p>Celery本身不提供消息服务，但是可以方便的和第三方提供的消息中间件集成。</p>
</blockquote>
<ul>
<li>任务执行单元</li>
</ul>
<blockquote>
<p>Task result store用来存储Worker执行的任务的结果，Celery支持以不同方式存储任务的结果</p>
</blockquote>
<hr>
<br>

<h2 id="celery作用"><a href="#celery作用" class="headerlink" title="celery作用"></a>celery作用</h2><ul>
<li>执行异步任务</li>
<li>执行延时任务</li>
<li>执行定时任务</li>
</ul>
<hr>
<br>

<h2 id="安装组件"><a href="#安装组件" class="headerlink" title="安装组件"></a>安装组件</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install celery</span><br></pre></td></tr></table></figure>
<hr>
<br>

<h2 id="celery使用"><a href="#celery使用" class="headerlink" title="celery使用"></a>celery使用</h2><ul>
<li>导入celery模块 创建celery_tasks/main.py文件</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">from celery import Celery</span><br></pre></td></tr></table></figure>
<ul>
<li>创建celery实例对象</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 创建celery实例</span><br><span class="line">app &#x3D; Celery(&#39;脚本名&#39;)</span><br><span class="line"># 加载配置文件  注意从celery文件夹开始</span><br><span class="line">app.config_from(&#39;celery配置文件位置&#39;)</span><br><span class="line"># 设置自动加载任务</span><br><span class="line">app.autodiscover_tasks([&#39;celery_tasks.任务名&#39;])</span><br></pre></td></tr></table></figure>
<ul>
<li>创建中间人broker</li>
</ul>
<h3 id="redis是一款功能完备的broker可选项"><a href="#redis是一款功能完备的broker可选项" class="headerlink" title="redis是一款功能完备的broker可选项"></a>redis是一款功能完备的broker可选项</h3><ul>
<li>创建任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">from libs.yuntongxun.sms import CCP</span><br><span class="line">from celery_tasks.main import app</span><br><span class="line"></span><br><span class="line">#可以设置name参数</span><br><span class="line">@app.task(name&#x3D;&#39;send_sms_code&#39;)   # 使用celery实例对象装饰@app.task()</span><br><span class="line">def send_sms_code(mobile,sms_code):</span><br><span class="line"></span><br><span class="line">    ccp &#x3D; CCP()</span><br><span class="line">    ccp.send_template_sms(mobile, [sms_code, 5], 1)</span><br></pre></td></tr></table></figure>
<ul>
<li>检测任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">app.autodiscover_tasks([&#39;celery_tasks.任务名&#39;])</span><br></pre></td></tr></table></figure>
<ul>
<li>创建worker</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">from celery import Celery</span><br><span class="line"></span><br><span class="line">#进行Celery允许配置</span><br><span class="line"># 为celery使用django配置文件进行设置</span><br><span class="line">import os</span><br><span class="line">if not os.getenv(&#39;DJANGO_SETTINGS_MODULE&#39;):</span><br><span class="line">    os.environ[&#39;DJANGO_SETTINGS_MODULE&#39;] &#x3D; &#39;mall.settings&#39;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#创建Celery对象</span><br><span class="line">#参数main 设置脚本名</span><br><span class="line">app &#x3D; Celery(&#39;celery_tasks&#39;)</span><br><span class="line"></span><br><span class="line">#加载配置文件</span><br><span class="line">app.config_from_object(&#39;celery_tasks.config&#39;)</span><br><span class="line"></span><br><span class="line">#自动加载任务</span><br><span class="line">app.autodiscover_tasks([&#39;celery_tasks.sms&#39;])</span><br></pre></td></tr></table></figure>
<ul>
<li>最后使用指令执行</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">celery -A celery对象的路径 worker -l info</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/01/30/celery%E5%BC%82%E6%AD%A5%E6%A1%86%E6%9E%B6(5.0)/" data-id="ckkt9opfp0001i4tw3qi21gyw" data-title="celery异步框架5.0" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-三方支付" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/01/29/%E4%B8%89%E6%96%B9%E6%94%AF%E4%BB%98/" class="article-date">
  <time class="dt-published" datetime="2021-01-28T16:00:00.000Z" itemprop="datePublished">2021-01-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/01/29/%E4%B8%89%E6%96%B9%E6%94%AF%E4%BB%98/">三方支付</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="配置沙箱环境"><a href="#配置沙箱环境" class="headerlink" title="配置沙箱环境"></a>配置沙箱环境</h2><p><a target="_blank" rel="noopener" href="https://open.alipay.com/platform/home.htm">https://open.alipay.com/platform/home.htm</a></p>
<ul>
<li><p>进入管理中心<br><img src="/hexo/.io//1.jpg" alt="1"></p>
</li>
<li><p>开发服务中的研发服务<br><img src="/hexo/.io//2.png" alt="2"></p>
</li>
<li><p>进入沙箱环境<br><img src="/hexo/.io//3.png" alt="3"></p>
</li>
<li><p>设置密钥<br><img src="/hexo/.io//4.png" alt="4"><br><img src="/hexo/.io//5.png" alt="5"></p>
</li>
<li><p>用支付宝开放平台开发助手生成公钥复制到<br><img src="/hexo/.io//6.png" alt="6"></p>
</li>
<li><p>保存设置<br><img src="/hexo/.io//7.png" alt="7"><br><img src="/hexo/.io//8.png" alt="8"></p>
</li>
<li><p>设置授权回调地址<br><img src="/hexo/.io//9.png" alt="9"></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">注意：这里需要在后端设置路由协同操作，</span><br></pre></td></tr></table></figure>
<p><img src="/hexo/.io//10.png" alt="10"></p>
</li>
</ul>
<h2 id="流程图"><a href="#流程图" class="headerlink" title="流程图"></a>流程图</h2><p><img src="/hexo/.io//11.png" alt="11"></p>
<h2 id="下载SDK插件"><a href="#下载SDK插件" class="headerlink" title="下载SDK插件"></a>下载SDK插件</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install python-alipay-sdk --upgrade</span><br></pre></td></tr></table></figure>
<h2 id="发起支付"><a href="#发起支付" class="headerlink" title="发起支付"></a>发起支付</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">class AliPayBackView(View):</span><br><span class="line"></span><br><span class="line">    def get(self, request):</span><br><span class="line">        user &#x3D; request.user</span><br><span class="line">        # 获取回调的信息</span><br><span class="line">        # 获取 订单号</span><br><span class="line">        sn &#x3D; request.GET.get(&quot;out_trade_no&quot;)</span><br><span class="line">        #  获取 支付宝交易号</span><br><span class="line">        trade_no &#x3D; request.GET.get(&quot;trade_no&quot;)</span><br><span class="line">        print(&quot;sn:&quot;, sn)</span><br><span class="line">        print(&quot;trade_no:&quot;, trade_no)</span><br><span class="line">        # 找到这个订单 并更新状态</span><br><span class="line">        # 修改了  订单状态  并添加了 支付宝交易号</span><br><span class="line">        Order.objects.filter(sn&#x3D;sn).update(trade_no&#x3D;trade_no, status&#x3D;2)</span><br><span class="line">        #  删除我们购物车中的 已经支付成功的购物信息</span><br><span class="line">        print(user)</span><br><span class="line">        # 查询所有的选中 然后删除</span><br><span class="line">        gid_set &#x3D; r.smembers(&quot;select_%d&quot; % user.id)</span><br><span class="line">        print(&quot;gid_set:&quot;, gid_set)</span><br><span class="line">        for gid in gid_set:</span><br><span class="line">            r.hdel(&quot;cart_%d&quot; % user.id, gid)</span><br><span class="line"></span><br><span class="line">        return redirect(&quot;http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;#&#x2F;paysuccess?trade_no&#x3D;&quot; + trade_no)</span><br></pre></td></tr></table></figure>
<h2 id="设置回调"><a href="#设置回调" class="headerlink" title="设置回调"></a>设置回调</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"># 设置回调地址</span><br><span class="line">class AliPayBackView(View):</span><br><span class="line"></span><br><span class="line">    def get(self, request):</span><br><span class="line">        user &#x3D; request.user</span><br><span class="line">        # 获取回调的信息</span><br><span class="line">        # 获取 订单号</span><br><span class="line">        sn &#x3D; request.GET.get(&quot;out_trade_no&quot;)</span><br><span class="line">        #  获取 支付宝交易号</span><br><span class="line">        trade_no &#x3D; request.GET.get(&quot;trade_no&quot;)</span><br><span class="line">        print(&quot;sn:&quot;, sn)</span><br><span class="line">        print(&quot;trade_no:&quot;, trade_no)</span><br><span class="line">        # 找到这个订单 并更新状态</span><br><span class="line">        # 修改了  订单状态  并添加了 支付宝交易号</span><br><span class="line">        Order.objects.filter(sn&#x3D;sn).update(trade_no&#x3D;trade_no, status&#x3D;2)</span><br><span class="line">        #  删除我们购物车中的 已经支付成功的购物信息</span><br><span class="line">        print(user)</span><br><span class="line">        # 查询所有的选中 然后删除</span><br><span class="line">        gid_set &#x3D; r.smembers(&quot;select_%d&quot; % user.id)</span><br><span class="line">        print(&quot;gid_set:&quot;, gid_set)</span><br><span class="line">        for gid in gid_set:</span><br><span class="line">            r.hdel(&quot;cart_%d&quot; % user.id, gid)</span><br><span class="line"></span><br><span class="line">        return redirect(&quot;http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;#&#x2F;paysuccess?trade_no&#x3D;&quot; + trade_no)</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/01/29/%E4%B8%89%E6%96%B9%E6%94%AF%E4%BB%98/" data-id="ckkt9opgb000ki4twdx3c6wjn" data-title="三方支付" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-微博第三方登录" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/01/28/%E5%BE%AE%E5%8D%9A%E7%AC%AC%E4%B8%89%E6%96%B9%E7%99%BB%E5%BD%95/" class="article-date">
  <time class="dt-published" datetime="2021-01-27T16:00:00.000Z" itemprop="datePublished">2021-01-28</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/01/28/%E5%BE%AE%E5%8D%9A%E7%AC%AC%E4%B8%89%E6%96%B9%E7%99%BB%E5%BD%95/">微博三方登录</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="微博三方登录流程"><a href="#微博三方登录流程" class="headerlink" title="微博三方登录流程"></a>微博三方登录流程</h2><ul>
<li>vue端发送post请求，获取微博的扫码URL</li>
<li>django端返回微博的URL</li>
<li>vue通过URL跳转到微博的扫码页面</li>
<li>微博端扫码后，跳转的vue端那个，redirect_uri的地址上，并且会携带一个code码，通过这个code码就可以到微博中查询到扫码人的微博信息</li>
<li>vue端把这个code交给了django</li>
<li>django端获取到code，并使用code到微博点查询用户信息</li>
<li>如果用户已经帮点过，直接登录成功，如果用户没有绑定过，返回微博的用户ID</li>
<li>如果返回的type=0，用户已经绑定过，直接跳转到首页，如果返回的type!=0，携带微博UID跳转到绑定页面</li>
<li>在vue绑定页面中，发送用户名(username),密码(password),微博UID到django后端</li>
<li>如果用户存在，判断用户名和面试否正确，正确绑定，错误提示前端，如果用户名不存在，创建用户，并添加绑定关系</li>
</ul>
<br>

<h2 id="操作步骤"><a href="#操作步骤" class="headerlink" title="操作步骤"></a>操作步骤</h2><h3 id="注册微博开放平台"><a href="#注册微博开放平台" class="headerlink" title="注册微博开放平台"></a>注册微博开放平台</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">选择微链接-&gt;网站接入&#x3D;&gt;立即接入 新建一个应用</span><br></pre></td></tr></table></figure>
<h3 id="拿到appkey和appsecret-然后立即点击高级地址，填写回调地址"><a href="#拿到appkey和appsecret-然后立即点击高级地址，填写回调地址" class="headerlink" title="拿到appkey和appsecret,然后立即点击高级地址，填写回调地址"></a>拿到appkey和appsecret,然后立即点击高级地址，填写回调地址</h3><h4 id="注意：回调授权和取消回调授权地址需要一致"><a href="#注意：回调授权和取消回调授权地址需要一致" class="headerlink" title="注意：回调授权和取消回调授权地址需要一致"></a>注意：回调授权和取消回调授权地址需要一致</h4><br>

<h4 id="那么新浪微博的登录逻辑很简单：-拼接url-gt-回调获取code-gt-利用code换取uid和access-token-gt-使用access-token获取用户信息"><a href="#那么新浪微博的登录逻辑很简单：-拼接url-gt-回调获取code-gt-利用code换取uid和access-token-gt-使用access-token获取用户信息" class="headerlink" title="那么新浪微博的登录逻辑很简单： 拼接url =&gt; 回调获取code =&gt; 利用code换取uid和access_token =&gt; 使用access_token获取用户信息"></a>那么新浪微博的登录逻辑很简单： 拼接url =&gt; 回调获取code =&gt; 利用code换取uid和access_token =&gt; 使用access_token获取用户信息</h4><hr>
<br>

<h3 id="后端"><a href="#后端" class="headerlink" title="后端"></a>后端</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"># 定义微博回调视图</span><br><span class="line">def wb_back(request):</span><br><span class="line">    # 获取回调的code</span><br><span class="line">    code &#x3D; request.GET.get(&#39;code&#39;)</span><br><span class="line">    # 定义认证地址</span><br><span class="line">    access_token_url &#x3D; &#39;https:&#x2F;&#x2F;api.weibo.com&#x2F;oauth2&#x2F;access_token&#39;</span><br><span class="line">    # 发起请求，交换sina的id</span><br><span class="line">    re_dict &#x3D; requests.post(</span><br><span class="line">        access_token_url,</span><br><span class="line">        data&#x3D;&#123;</span><br><span class="line">            &quot;client_id&quot;: &#39;2636039333&#39;,  # 应用id</span><br><span class="line">            &quot;client_secret&quot;: &quot;*************************&quot;,  # 密钥</span><br><span class="line">            &quot;grant_type&quot;: &quot;authorization_code&quot;,  # 授权方式</span><br><span class="line">            &quot;code&quot;: code,  # code</span><br><span class="line">            &quot;redirect_uri&quot;: &quot;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;weibo_back&quot;  # 回调网址</span><br><span class="line">        &#125;</span><br><span class="line">    )</span><br><span class="line">    # 获取返回值</span><br><span class="line">    re_dict &#x3D; re_dict.text</span><br><span class="line">    # 强转</span><br><span class="line">    re_dict &#x3D; eval(re_dict)</span><br><span class="line">    print(re_dict)</span><br><span class="line">    # 判断是否为第一次登陆</span><br><span class="line">    user &#x3D; User.objects.filter(username&#x3D;str(re_dict[&#39;uid&#39;])).first()</span><br><span class="line">    if user:</span><br><span class="line">        # 代表曾经用过新浪登录</span><br><span class="line">        sina_id &#x3D; user.username</span><br><span class="line">        user_id &#x3D; user.id</span><br><span class="line">    else:</span><br><span class="line">        # 代表首次登陆</span><br><span class="line">        user &#x3D; User(username&#x3D;str(re_dict[&#39;uid&#39;]),password&#x3D;&#39;&#39;)</span><br><span class="line">        # 保存入库</span><br><span class="line">        user.save()</span><br><span class="line">        sina_id &#x3D; str(re_dict[&#39;uid&#39;])</span><br><span class="line">        # 查询用户id</span><br><span class="line">        user &#x3D; User.objects.filter(username&#x3D;str(re_dict[&#39;uid&#39;])).first()</span><br><span class="line">        user_id &#x3D; user.id</span><br><span class="line">    #进行跳转</span><br><span class="line">    return redirect(&#39;http:&#x2F;&#x2F;localhost:8080?sina_id&#x3D;&#39;+str(sina_id)+&#39;&amp;uid&#x3D;&#39;+str(user_id))</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<hr>
<br>

<h3 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 跳转到新浪微博</span><br><span class="line">    sinalogin:function()&#123;</span><br><span class="line">      &#x2F;&#x2F; 应用id client_id&#x3D;2636039333</span><br><span class="line">      &#x2F;&#x2F;redirect_url： 回调网址</span><br><span class="line"></span><br><span class="line">      &#x2F;&#x2F; 拼接新浪url</span><br><span class="line">      let url &#x3D; &quot;https:&#x2F;&#x2F;api.weibo.com&#x2F;oauth2&#x2F;authorize?client_id&#x3D;2636039333&amp;redirect_uri&#x3D;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;weibo&quot;;</span><br><span class="line">      &#x2F;&#x2F; 进行站外跳转</span><br><span class="line">      window.location.href &#x3D; url;</span><br><span class="line"></span><br><span class="line">    &#125;,</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/01/28/%E5%BE%AE%E5%8D%9A%E7%AC%AC%E4%B8%89%E6%96%B9%E7%99%BB%E5%BD%95/" data-id="ckkt9opg2000gi4tweouo74xq" data-title="微博三方登录" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-vue父子组件、子父组件" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/hexo/2021/01/27/vue%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E3%80%81%E5%AD%90%E7%88%B6%E7%BB%84%E4%BB%B6/" class="article-date">
  <time class="dt-published" datetime="2021-01-26T16:00:00.000Z" itemprop="datePublished">2021-01-27</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/hexo/2021/01/27/vue%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E3%80%81%E5%AD%90%E7%88%B6%E7%BB%84%E4%BB%B6/">vue父子组件、子父组件</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="什么是vue父子组件"><a href="#什么是vue父子组件" class="headerlink" title="什么是vue父子组件"></a>什么是vue父子组件</h1><h3 id="一个vue实例就是一个组件，这里叫a。-我们定义了一个组件之后把它放到另外一个vue实例中，另外的那个就叫b，然后我们就可以说a是b的子组件，因为a在b中使用，也可以看成a成了b的一个元素。"><a href="#一个vue实例就是一个组件，这里叫a。-我们定义了一个组件之后把它放到另外一个vue实例中，另外的那个就叫b，然后我们就可以说a是b的子组件，因为a在b中使用，也可以看成a成了b的一个元素。" class="headerlink" title="一个vue实例就是一个组件，这里叫a。 我们定义了一个组件之后把它放到另外一个vue实例中，另外的那个就叫b，然后我们就可以说a是b的子组件，因为a在b中使用，也可以看成a成了b的一个元素。"></a>一个vue实例就是一个组件，这里叫a。 我们定义了一个组件之后把它放到另外一个vue实例中，另外的那个就叫b，然后我们就可以说a是b的子组件，因为a在b中使用，也可以看成a成了b的一个元素。</h3><br>

<ul>
<li>所谓的父向子就是 b vue实例中的data值传到了组件中使用。 </li>
<li>子向父就是 把组件a中的data 传递到了a中。</li>
</ul>
<hr>
<br>

<h2 id="父传子"><a href="#父传子" class="headerlink" title="父传子"></a>父传子</h2><h3 id="父向子传值用props，props生成组件的属性，当它化生成一个子组件在a中使用的时候，可以通过直接在元素上控制属性，或者通过父实例中的data获取值来改变组件的属性值。"><a href="#父向子传值用props，props生成组件的属性，当它化生成一个子组件在a中使用的时候，可以通过直接在元素上控制属性，或者通过父实例中的data获取值来改变组件的属性值。" class="headerlink" title="父向子传值用props，props生成组件的属性，当它化生成一个子组件在a中使用的时候，可以通过直接在元素上控制属性，或者通过父实例中的data获取值来改变组件的属性值。"></a>父向子传值用props，props生成组件的属性，当它化生成一个子组件在a中使用的时候，可以通过直接在元素上控制属性，或者通过父实例中的data获取值来改变组件的属性值。</h3><br>
分别创建两个文件PKTable.vue子组件和APP.vue父组件

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;父组件传值（App.vue）静态的值</span><br><span class="line">&lt;PkTable data&#x3D;&quot;aaaaaa&quot;&gt;&lt;&#x2F;PkTable&gt;</span><br><span class="line">&#x2F;&#x2F;父组件传值 动态的值</span><br><span class="line">&lt;PkTable :data&#x3D;&quot;parentData&quot;&gt;&lt;&#x2F;PkTable&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">import PkTabel from &#39;@&#x2F;components&#x2F;PKATMRecord&#x2F;PKTabel.vue&#39;;</span><br><span class="line">export default &#123;</span><br><span class="line">  name: &#39;App&#39;,</span><br><span class="line">  data()&#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      parentData:&quot;这是父组件的数据&quot;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  components: &#123;</span><br><span class="line">    PkTabel</span><br><span class="line">  &#125;,</span><br><span class="line">  &#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;子组件接收（PkTable.vue）</span><br><span class="line">&lt;h1&gt;&#123;&#123;parentData&#125;&#125;&lt;&#x2F;h1&gt;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">  name: &#39;HelloWorld&#39;,</span><br><span class="line">  props: &#123;</span><br><span class="line">    parentData: String,</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<hr>
<br>

<h2 id="子传父"><a href="#子传父" class="headerlink" title="子传父"></a>子传父</h2><h3 id="子组件向父组件传值-要用事件。-运用-emit-运用-emit来创建一个事件，把该属性值传到父组件中，父组件里要监听这个事件，通过这个事件来产生值的变化"><a href="#子组件向父组件传值-要用事件。-运用-emit-运用-emit来创建一个事件，把该属性值传到父组件中，父组件里要监听这个事件，通过这个事件来产生值的变化" class="headerlink" title="子组件向父组件传值 要用事件。 运用$emit,运用$emit来创建一个事件，把该属性值传到父组件中，父组件里要监听这个事件，通过这个事件来产生值的变化"></a>子组件向父组件传值 要用事件。 运用$emit,运用$emit来创建一个事件，把该属性值传到父组件中，父组件里要监听这个事件，通过这个事件来产生值的变化</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;子组件</span><br><span class="line">&lt;button @click.stop&#x3D;&quot;changParent&quot;&gt;按钮&lt;&#x2F;button&gt;</span><br><span class="line"></span><br><span class="line">methods:&#123;</span><br><span class="line">  changParent()&#123;</span><br><span class="line">  this.$emit(&#39;childFn&#39;,&#39;childData&#39;)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;父组件</span><br><span class="line">&lt;PkTable :data&#x3D;&quot;parentData&quot; @childFn&#x3D;&quot;parentMethod&quot;&gt;&lt;&#x2F;PkTable&gt;</span><br><span class="line"></span><br><span class="line">methods:&#123;</span><br><span class="line">  parentMethod(msg)&#123;</span><br><span class="line">  	console.log(msg);  &#x2F;&#x2F;&#39;childData&#39;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://mourning-soul.gitee.io/hexo/2021/01/27/vue%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E3%80%81%E5%AD%90%E7%88%B6%E7%BB%84%E4%BB%B6/" data-id="ckkt9opfy000ai4twfk9n3y7e" data-title="vue父子组件、子父组件" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>

    </footer>
  </div>
  
</article>



  


  <nav id="page-nav">
    
    <span class="page-number current">1</span><a class="page-number" href="/hexo/page/2/">2</a><a class="extend next" rel="next" href="/hexo/page/2/">Next &raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/hexo/tags/blocker/" rel="tag">-blocker</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/hexo/tags/blocker/" style="font-size: 10px;">-blocker</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/hexo/archives/2021/02/">February 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/hexo/archives/2021/01/">January 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/hexo/2021/02/05/%E8%A7%86%E9%A2%91%E7%9B%B4%E6%92%AD/">视频直播</a>
          </li>
        
          <li>
            <a href="/hexo/2021/02/04/%E6%97%A0%E9%99%90%E6%9E%81%E5%88%86%E7%B1%BB%E8%87%AA%E5%85%B3%E8%81%94%E9%80%92%E5%BD%92/">无限极分类自关联递归</a>
          </li>
        
          <li>
            <a href="/hexo/2021/02/03/webshell/">webshell</a>
          </li>
        
          <li>
            <a href="/hexo/2021/02/02/redis%E9%94%AE%E7%A9%BA%E9%97%B4%E4%BA%8B%E4%BB%B6/">redis键空间事件</a>
          </li>
        
          <li>
            <a href="/hexo/2021/02/01/redis%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/">redis发布者订阅者</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2021 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/hexo/" class="mobile-nav-link">Home</a>
  
    <a href="/hexo/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/hexo/js/jquery-3.4.1.min.js"></script>



  
<script src="/hexo/fancybox/jquery.fancybox.min.js"></script>




<script src="/hexo/js/script.js"></script>





  </div>
</body>
</html>